//
//  FPluginTableViewProxy.m
//  Foundation
//
//  Created by 吴新庭 on 2019/7/15.
//

#import "FPluginTableViewProxy.h"
#import "FPluginFakeTableView.h"
#import "FPlugin.h"
#import "FPluginWrappedData.h"
#import "UITableView+FPlugin.h"

@interface FPluginTableViewProxy () <UITableViewDelegate, UITableViewDataSource>

@property (nonatomic, weak) UITableView *sourceTable;
@property (nonatomic, weak) id<UITableViewDataSource> sourceDataSource;
@property (nonatomic, weak) id<UITableViewDelegate> sourceDelegate;

@end

@implementation FPluginTableViewProxy

- (instancetype)initWithSource:(UITableView *)table {
    if (self = [super init]) {
        self.sourceTable = table;
        
        self.sourceDelegate = table.delegate;
        self.sourceDataSource = table.dataSource;
        self.sourceTable.delegate = self;
        self.sourceTable.dataSource = self;
    }
    return self;
}

- (FPluginFake *)prepareArg:(FPluginArg *)arg forPlugin:(id<FPlugin>)plugin {
    FPluginFake *fake = [super prepareArg:arg forPlugin:plugin];
    arg.tableView = (UITableView *)fake;
    return fake;
}

- (FPluginFake *)fakeForIdentifier:(NSString *)identifier {
    return [FPluginFakeTableView fakeFor:self.sourceTable];
}

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    __block NSUInteger num = 0;
    
    if ([self.sourceDataSource respondsToSelector:_cmd]) {
        num += [self.sourceDataSource numberOfSectionsInTableView:tableView];
    }
    
    [self.pluginFakeMap enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, FPluginFakeTableView * _Nonnull obj, BOOL * _Nonnull stop) {
        if ([obj.dataSource respondsToSelector:@selector(numberOfSectionsInTableView:)]) {
            num += [obj.dataSource numberOfSectionsInTableView:(UITableView *)obj];
        } else {
            num += 1;
        }
    }];
    
    if (num <= 1) {
        self.sectionType = FPluginArraySectionTypeSingle;
    } else if (num <= tableView.plg_datas.sectionNum) {
        // 比自然组少，比1大
        num = tableView.plg_datas.sectionNum;
        self.sectionType = FPluginArraySectionTypeNatural;
    } else if (num <= tableView.plg_datas.count) {
        // 比自然组大，比完全组少
        num = tableView.plg_datas.count;
        self.sectionType = FPluginArraySectionTypeEntire;
    } else {
        // 比完全组还大
        num = tableView.plg_datas.count;
        self.sectionType = FPluginArraySectionTypeEntire;
    }
    return num;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [tableView.plg_datas numberOfItemsInSection:section withSectionType:self.sectionType];
}

- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    FPluginWrappedData *data = [tableView objectAtIndexPath:indexPath];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    if ([fake.dataSource respondsToSelector:@selector(tableView:cellForRowAtIndexPath:)]) {
        UITableViewCell *cell = [fake.dataSource tableView:(UITableView *)fake cellForRowAtIndexPath:indexPath];
        if (cell) {
            return cell;
        }
    }
    return [self.sourceDataSource tableView:tableView cellForRowAtIndexPath:indexPath];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    FPluginWrappedData *data = [tableView objectAtIndexPath:indexPath];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    FPlugin_Proxy_Return(CGFloat, fake.delegate, self.sourceDelegate, fake, tableView, indexPath);
    
    return tableView.rowHeight;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    FPluginWrappedData *data = [tableView objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    
    if ([fake.delegate respondsToSelector:_cmd]) {
        return [fake.delegate tableView:(UITableView *)fake heightForHeaderInSection:section];
    }
    
    if ([self.sourceDelegate respondsToSelector:_cmd]) {
        return [self.sourceDelegate tableView:tableView heightForHeaderInSection:section];
    }
    
    return tableView.sectionHeaderHeight;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    FPluginWrappedData *data = [tableView objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    
    if ([fake.delegate respondsToSelector:_cmd]) {
        return [fake.delegate tableView:(UITableView *)fake heightForFooterInSection:section];
    }
    
    if ([self.sourceDelegate respondsToSelector:_cmd]) {
        return [self.sourceDelegate tableView:tableView heightForFooterInSection:section];
    }
    
    return tableView.sectionFooterHeight;
}

- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section {
    FPluginWrappedData *data = [tableView objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    if ([fake.delegate respondsToSelector:_cmd]) {
        return [fake.delegate tableView:(UITableView *)fake willDisplayFooterView:view forSection:section];
    }
    
    if ([self.sourceDelegate respondsToSelector:_cmd]) {
        return [self.sourceDelegate tableView:tableView willDisplayFooterView:view forSection:section];
    }
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    FPluginWrappedData *data = [tableView objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    if ([fake.dataSource respondsToSelector:@selector(tableView:titleForHeaderInSection:)]) {
        return [fake.dataSource tableView:(UITableView *)fake titleForHeaderInSection:section];
    }
    if ([self.sourceDataSource respondsToSelector:@selector(tableView:titleForHeaderInSection:)]) {
        return [self.sourceDataSource tableView:tableView titleForHeaderInSection:section];
    }
    return nil;
}

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
    FPluginWrappedData *data = [tableView objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    if ([fake.dataSource respondsToSelector:@selector(tableView:titleForFooterInSection:)]) {
        return [fake.dataSource tableView:(UITableView *)fake titleForFooterInSection:section];
    }
    if ([self.sourceDataSource respondsToSelector:@selector(tableView:titleForFooterInSection:)]) {
        return [self.sourceDataSource tableView:tableView titleForFooterInSection:section];
    }
    return nil;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    FPluginWrappedData *data = [tableView objectAtIndexPath:indexPath];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    if ([fake.delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) {
        [fake.delegate tableView:(UITableView *)fake didSelectRowAtIndexPath:indexPath];
        return;
    }
    
    if ([self.sourceDelegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) {
        [self.sourceDelegate tableView:tableView didSelectRowAtIndexPath:indexPath];
    }
}

#pragma mark -
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    FPluginWrappedData *data = [tableView objectAtIndexPath:indexPath];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    
    if ([fake.dataSource respondsToSelector:@selector(tableView:canEditRowAtIndexPath:)]) {
        return [fake.dataSource tableView:(UITableView *)fake canEditRowAtIndexPath:indexPath];
    }
    
    if ([self.sourceDataSource respondsToSelector:@selector(tableView:canEditRowAtIndexPath:)]) {
        return [self.sourceDataSource tableView:tableView canEditRowAtIndexPath:indexPath];
    }
    return NO;
}

- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
    FPluginWrappedData *data = [tableView objectAtIndexPath:indexPath];
    FPluginFakeTableView *fake = (FPluginFakeTableView *)[self fakeForData:data];
    
    if ([fake.delegate respondsToSelector:@selector(tableView:editActionsForRowAtIndexPath:)]) {
        return [fake.delegate tableView:(UITableView *)fake editActionsForRowAtIndexPath:indexPath];
    }
    
    if ([self.sourceDelegate respondsToSelector:@selector(tableView:editActionsForRowAtIndexPath:)]) {
        return [self.sourceDelegate tableView:tableView editActionsForRowAtIndexPath:indexPath];
    }
    return nil;
}

#pragma mark -
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    for (FPluginFakeTableView *fake in self.pluginFakeMap.allValues) {
        F_macro_delegate(void, fake.delegate, _cmd, fake);
    }
    F_macro_delegate(void, self.sourceDelegate, _cmd, scrollView);
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    for (FPluginFakeTableView *fake in self.pluginFakeMap.allValues) {
        F_macro_delegate(void, fake.delegate, _cmd, fake);
    }
    F_macro_delegate(void, self.sourceDelegate, _cmd, scrollView);
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    for (FPluginFakeTableView *fake in self.pluginFakeMap.allValues) {
        if ([fake.delegate respondsToSelector:_cmd]) {
            [fake.delegate scrollViewDidEndDragging:(UIScrollView *)fake willDecelerate:decelerate];
        }
    }
    if ([self.sourceDelegate respondsToSelector:_cmd]) {
        [self.sourceDelegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
    }
}

@end
